/**
 * @fileoverview 项目配置向导优化模块
 * 提供更丰富的配置选项和详细说明，增强用户交互体验
 */

import { default as chalk } from "chalk";
import { resolve, isAbsolute } from "path";
import inquirer from "inquirer";
import { errorHandler } from "./error-handler.js";

/**
 * 配置向导选项
 * @typedef {Object} WizardOptions
 * @property {boolean} [useDefaultsOnError=true] - 发生错误时是否使用默认值
 */

/**
 * 配置向导结果
 * @typedef {Object} WizardResult
 * @property {Object} answers - 用户回答的所有配置项
 * @property {string} basepath - 项目基础路径
 * @property {null} selectedTemplate - 选择的项目模板，始终为null
 */

/**
 * 配置向导类
 */
class ConfigWizard {
  /**
   * 创建配置向导实例
   * @param {WizardOptions} options - 配置选项
   */
  constructor(options = {}) {
    this.options = {
      showTemplates: false, // 禁用模板选择
      showAdvancedOptions: false, // 禁用高级选项
      useDefaultsOnError: options.useDefaultsOnError !== false,
    };
  }

  /**
   * 运行配置向导
   * @returns {Promise<WizardResult>} 配置向导结果
   */
  async run() {
    try {
      // 显示欢迎信息
      this._showWelcomeMessage();

      // 收集基础配置
      const answers = await this._collectBasicConfig();

      // 根据项目类型决定是否显示服务端/客户端选择
      await this._collectServerClientConfig(answers);

      // 收集项目路径
      const basepath = await this._collectProjectPath();

      // 显示配置摘要
      this._showConfigSummary(answers, basepath, null);

      return {
        answers,
        basepath,
        selectedTemplate: null,
      };
    } catch (error) {
      // 只有在真正发生错误时才记录错误日志
      await errorHandler.handleError(
        error,
        "CONFIGURATION",
        "运行配置向导",
        () => {
          console.error(chalk.red("配置向导出错:"), error.message);
        }
      );

      // 如果配置为出错时使用默认值，则返回默认配置
      if (this.options.useDefaultsOnError) {
        console.log(chalk.yellow("\n⚠️ 使用默认配置继续..."));
        return this._getDefaultConfig();
      }

      throw error;
    }
  }

  /**
   * 显示欢迎信息
   * @private
   */
  _showWelcomeMessage() {
    console.log(chalk.bold.cyan("\n🎮 欢迎使用神奇代码岛项目创建向导！"));
    console.log(chalk.cyan("让我们一起定制你的神岛代码项目吧！"));
    console.log(
      chalk.dim("\n📚 在线文档：") +
        chalk.blue("https://docs.dao3.fun/arenapro/") +
        "\n"
    );
  }

  /**
   * 收集基础配置
   * @returns {Promise<Object>} 基础配置对象
   * @private
   */
  async _collectBasicConfig() {
    const basicQuestions = [
      {
        type: "list",
        name: "npmPackage",
        message: "🎯 选择项目类型",
        choices: [
          {
            name: "神岛地图项目",
            value: "神岛地图项目",
            short: "神岛地图项目",
          },
          {
            name: "神岛组件库",
            value: "神岛组件库",
            short: "神岛组件库",
          },
        ],
        default: "神岛地图项目",
        description:
          "神岛地图项目适合开发游戏地图，神岛组件库则用于开发可复用的功能模块。",
      },
      {
        type: "list",
        name: "languageType",
        message: "🔧 选择开发语言",
        choices: [
          {
            name: "TypeScript",
            value: "TypeScript",
            short: "TypeScript",
          },
          {
            name: "JavaScript",
            value: "JavaScript",
            short: "JavaScript",
          },
        ],
        default: "TypeScript",
        description:
          "TypeScript提供类型检查，帮助捕获常见错误并提升开发体验；JavaScript更加灵活，但缺少静态类型检查。",
      },
      {
        type: "list",
        name: "prettier",
        message: "📝 是否配置代码规范工具",
        choices: [
          {
            name: "配置 - 包含ESLint和Prettier",
            value: "配置",
            short: "配置",
          },
          {
            name: "跳过 - 不使用代码规范工具",
            value: "跳过",
            short: "跳过",
          },
        ],
        description:
          "ESLint和Prettier可以帮助保持一致的代码风格，提高代码质量和可读性。",
      },
      {
        type: "list",
        name: "i18n",
        message: "💬 是否配置国际化",
        choices: [
          {
            name: "配置 - 包含i18n",
            value: "配置",
            short: "配置",
          },
          {
            name: "跳过 - 不使用i18n",
            value: "跳过",
            short: "跳过",
          },
        ],
        description:
          "国际化 (i18n) 方案将帮助你的项目支持多种语言，触及更广泛的用户群体。",
      },
      {
        type: "list",
        name: "dependentManner",
        message: "📦 项目依赖方式",
        choices: [
          {
            name: "npm - 默认",
            value: "npm",
            short: "npm",
          },
          {
            name: "yarn",
            value: "yarn",
            short: "yarn",
          },
          {
            name: "pnpm",
            value: "pnpm",
            short: "pnpm",
          },
          {
            name: "bun",
            value: "bun",
            short: "bun",
          },
        ],
        default: "npm",
        description:
          "请选择包管理器。npm 已内置，推荐使用 yarn 或 pnpm 以获得更佳性能，bun 为最新包管理器，性能更佳。",
      },
    ];

    const answers = {};
    for (let i = 0; i < basicQuestions.length; i++) {
      const question = basicQuestions[i];
      const { name, ...questionConfig } = question;

      // 显示问题描述
      if (question.description) {
        console.log(chalk.dim(`💡 ${question.description}`));
      }

      // 提问并收集答案
      const response = await inquirer.prompt({
        ...questionConfig,
        name: "value",
      });
      answers[name] = response;

      // 显示选择结果和提示
      console.log(chalk.green(`✓ 已选择: ${response.value}`));

      // 如果选择JavaScript，提供TypeScript的建议
      if (name === "languageType" && response.value === "JavaScript") {
        console.log(chalk.yellow("\n💡 温馨提示："));
        console.log(chalk.dim("TypeScript 能为你的项目带来以下好处："));
        console.log(
          chalk.dim("• 更好的类型检查，帮助你在开发阶段发现潜在问题")
        );
        console.log(chalk.dim("• 更强大的IDE支持，提供更准确的代码补全和重构"));
        console.log(chalk.dim("• 更容易维护的代码库，特别是在团队协作中"));
        console.log(chalk.dim("• 更好的类型提示和API文档集成"));
        console.log(chalk.dim("• 更强大的代码重构和重组能力"));
        console.log(
          chalk.dim(
            "这次使用 JavaScript 也没关系，但强烈建议你下次尝试 TypeScript，以获得更好的开发体验！\n"
          )
        );
      }

      // 如果选择配置代码规范，提供相关信息
      if (name === "prettier" && response.value === "配置") {
        console.log(chalk.cyan("\n💡 代码规范工具包括："));
        console.log(
          chalk.dim("• ESLint：静态代码分析工具，帮助发现和修复代码问题")
        );
        console.log(chalk.dim("• Prettier：代码格式化工具，统一代码风格"));
        console.log(
          chalk.dim("• Husky + lint-staged：Git提交前自动检查和格式化代码")
        );
        console.log(
          chalk.dim("• 配置文件：.eslintrc, .prettierrc, .lintstagedrc\n")
        );
      }

      // 如果选择配置国际化，提供相关信息
      if (name === "i18n" && response.value === "配置") {
        console.log(chalk.cyan("\n💡 国际化 (i18n) 方案包括："));
        console.log(chalk.dim("• i18next：国际化框架，支持多种语言切换"));
        console.log(chalk.dim("• 配置文件：i18n/\n"));
      }
    }

    return answers;
  }

  /**
   * 收集服务端/客户端配置
   * @param {Object} answers - 当前收集的配置
   * @returns {Promise<void>}
   * @private
   */
  async _collectServerClientConfig(answers) {
    // 初始化服务端/客户端配置
    answers.isServer = { value: "" };

    // 仅当项目类型为组件库时才需要选择
    if (answers.npmPackage.value === "神岛组件库") {
      console.log(chalk.cyan("\n🔍 组件库服务对象选择："));
      console.log(
        chalk.dim("• 服务端组件：运行在游戏服务器上，处理游戏逻辑、数据和规则")
      );
      console.log(
        chalk.dim("• 客户端组件：运行在玩家浏览器中，负责UI展示和用户交互")
      );

      answers.isServer = await inquirer.prompt({
        type: "list",
        name: "value",
        message: "请选择组件库的主要服务对象：",
        choices: [
          {
            name: "服务端 - 游戏逻辑和数据处理",
            value: "服务端",
            short: "服务端",
          },
          {
            name: "客户端 - 界面和用户交互",
            value: "客户端",
            short: "客户端",
          },
        ],
      });

      // 提供选择后的额外信息
      if (answers.isServer.value === "服务端") {
        console.log(chalk.cyan("\n💡 服务端组件开发提示："));
        console.log(chalk.dim("• 服务端组件可以访问游戏的完整数据和API"));
        console.log(chalk.dim("• 适合实现游戏规则、AI行为和数据处理"));
        console.log(chalk.dim("• 可以使用GameAPI服务端专用API\n"));
      } else {
        console.log(chalk.cyan("\n💡 客户端组件开发提示："));
        console.log(chalk.dim("• 客户端组件主要用于实现用户界面和交互"));
        console.log(chalk.dim("• 适合开发UI控件、视觉效果和用户输入处理"));
        console.log(chalk.dim("• 可以使用ClientAPI客户端专用API\n"));
      }

      console.log(chalk.green(`✓ 已选择: ${answers.isServer.value}`));
    }
  }

  /**
   * 收集项目路径
   * @returns {Promise<string>} 项目路径
   * @private
   */
  async _collectProjectPath() {
    console.log(chalk.cyan("\n[路径设置]"));
    console.log(chalk.dim("• 请输入项目名称，作为项目目录"));
    const { path } = await inquirer.prompt([
      {
        type: "input",
        name: "path",
        message: "📂 请输入项目创建的路径:",
        validate: (input) => {
          if (!input) {
            return "项目路径不能为空";
          }
          // 限制项目路径只能包含英文字母、数字、下划线、连字符、点和斜杠
          if (!/^[a-zA-Z0-9_./-]+$/.test(input)) {
            return "项目路径只能包含英文字母、数字、下划线、连字符、点 (.) 和斜杠 (/)";
          }
          return true;
        },
      },
    ]);
    return path;
  }

  /**
   * 显示配置摘要
   * @param {Object} answers - 收集的配置
   * @param {string} basepath - 项目路径
   * @param {null} selectedTemplate - 选择的项目模板
   * @private
   */
  _showConfigSummary(answers, basepath, selectedTemplate) {
    const fullPath = isAbsolute(basepath)
      ? basepath
      : resolve(process.cwd(), basepath);

    console.log(chalk.bold.greenBright("\n✅ 配置收集完成！"));
    console.log(chalk.cyan("以下是你的项目配置摘要："));
    console.log(chalk.dim("----------------------------------------"));

    console.log(chalk.cyan("📁 项目路径：") + " " + fullPath);
    console.log(chalk.cyan("🔧 基础配置："));
    console.log(`   • 项目类型：${answers.npmPackage.value}`);
    if (answers.isServer.value) {
      console.log(`   • 组件类型：${answers.isServer.value}`);
    }
    console.log(`   • 开发语言：${answers.languageType.value}`);
    console.log(`   • 代码规范：${answers.prettier.value}`);
    console.log(`   • 国际化：${answers.i18n.value}`);

    console.log(chalk.dim("----------------------------------------"));
    console.log(
      chalk.cyan("正在自动配置你的项目，请稍候...") +
        chalk.dim(" (这可能需要几分钟时间)\n")
    );
  }

  /**
   * 获取默认配置
   * @returns {WizardResult} 默认配置结果
   * @private
   */
  _getDefaultConfig() {
    const answers = {
      npmPackage: { value: "神岛地图项目" },
      languageType: { value: "TypeScript" },
      strict: { value: "启用" },
      prettier: { value: "配置" },
      isServer: { value: "" },
    };
    finalSources = getSources(answers);
    return {
      answers,
      basepath: ".",
      selectedTemplate: null,
    };
  }
}

// 导出配置向导类
export { ConfigWizard };
